package com.cekanet.mybudget;

import java.io.IOException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.cekanet.mybudget.dbutils.ProtectionException;
import com.cekanet.mybudget.dbutils.StatementHandler;
import com.cekanet.mybudget.dbutils.StatementItem;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;

@SuppressWarnings("serial")
public class QueryStatementServlet extends HttpServlet {
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		try {
			boolean isError = false;
			String errorDescription="Unknow error";
			List <StatementItem> statementItemList = null;
			try {
				statementItemList = this.doQuery(req);
			}catch (RequestParseException e){
				isError=true;
			} catch (UserException e) {
				errorDescription = "Cannot retrive user data in servlet";
				e.printStackTrace();
			} catch (ProtectionException e) {
				errorDescription = "You are not the owner of the record you are attempting to access/modify";
				e.printStackTrace();
			} catch (ParseException e) {
				errorDescription = "Error while reading request. Malformed XML ?";
				e.printStackTrace();
			}

			DocumentBuilderFactory docFactory= DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement("response");
			doc.appendChild(rootElement);


			Element exitStatus = doc.createElement("exitStatus");
			rootElement.appendChild(exitStatus);

			if (isError){
				exitStatus.setAttribute("status", "ERROR");
				Element statDescription = doc.createElement("description");
				exitStatus.appendChild(statDescription);
				statDescription.appendChild(doc.createTextNode(errorDescription));
			}else {
				exitStatus.setAttribute("status", "OK");
				Element statDescription = doc.createElement("description");
				exitStatus.appendChild(statDescription);
				statDescription.appendChild(doc.createTextNode("Job done !"));
				
				Element statementEl = doc.createElement("statement");
				rootElement.appendChild(statementEl);
				statementEl.setAttribute("type","partial");
				
				if(statementItemList!=null){

					DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
					DecimalFormat currencyFormat = new DecimalFormat();
					currencyFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ITALY));
					currencyFormat.setGroupingUsed(false);
					
					for (StatementItem statementItem : statementItemList){
						Element item = doc.createElement("item");
						statementEl.appendChild(item);
						item.setAttribute("id",statementItem.getId().toString());
	
						Element date = doc.createElement("date");
						date.appendChild(doc.createTextNode(dateFormat.format(statementItem.getDate())));
						item.appendChild(date);
	
						Element price = doc.createElement("price");
						price.appendChild(doc.createTextNode(currencyFormat.format(statementItem.getPrice())));
						item.appendChild(price);
	
						Element name = doc.createElement("name");
						name.appendChild(doc.createTextNode(statementItem.getName()));
						item.appendChild(name);
	
						Element description = doc.createElement("description");
						description.appendChild(doc.createTextNode(statementItem.getDescription()));
						item.appendChild(description);
					}
				}


				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);


				resp.setContentType("text/xml");
				StreamResult result = new StreamResult(resp.getWriter());
				transformer.transform(source, result);

			}
		} catch (ParserConfigurationException e) {

			e.printStackTrace();
		} catch (TransformerConfigurationException e) {

			e.printStackTrace();
		} catch (TransformerException e) {

			e.printStackTrace();
		}

	}

	private List <StatementItem> doQuery(HttpServletRequest req) throws IOException, RequestParseException, UserException, ProtectionException, ParseException{
		List <StatementItem> statementItemList = null;

		try {
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document requestDoc = dBuilder.parse(req.getInputStream());
			requestDoc.getDocumentElement().normalize();

			Element requestRootElement = requestDoc.getDocumentElement();
			if (!requestRootElement.getNodeName().equals("query"))
				throw new RequestParseException("Malformed request.");
			
			User user = UserServiceFactory.getUserService().getCurrentUser();
			if (user == null)
				throw new UserException("User service returned null.");
			
			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
			DecimalFormat currencyFormat = new DecimalFormat();
			currencyFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ITALY));
			currencyFormat.setGroupingUsed(false);
			
			StatementHandler statementHandler = new StatementHandler(user.getUserId());
			
			statementItemList = statementHandler.query(
					dateFormat.parse(requestRootElement.getElementsByTagName("startDate").item(0).getTextContent()),
					dateFormat.parse(requestRootElement.getElementsByTagName("stopDate").item(0).getTextContent()),
					requestRootElement.getElementsByTagName("name").item(0).getTextContent().trim().toUpperCase(),
					requestRootElement.getElementsByTagName("description").item(0).getTextContent().trim().toUpperCase()	
					);
			
		}catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new RequestParseException("Error.");
		} catch (SAXException e) {
			e.printStackTrace();
			throw new RequestParseException("Error.");
		}
		return statementItemList;
	}

}
